home *** CD-ROM | disk | FTP | other *** search
- ; This program calls Int 2F, function 1680h, to give OS/2, Desqview, etc.
- ; a chance to use wasted CPU cycles.
- ;
- ; The program also hooks the DOS multiplex interrupt, Int 2Fh, for an installation check.
- ;
- ; 08 Nov. 1995 -- 1st release -- Gives up just a little too much. Needs major work!!
- ;
- ; 09 Nov. 1995 -- 2nd release -- Fixed screwup in TSR paragraph calculation. Does not
- ; noticeably return CPU cycles, but no more bizarro
- ; lockups and segment faults.
- ;
- ; 10 Nov. 1995 -- 3rd release -- Modified code to use Int 2F, Function 1680h, Release
- ; current virtual machine time slice, instead of just
- ; calling the DOS idle interrupt. Found this in PC
- ; Interrupts, 2nd edition. Works well, but needs some
- ; tuning parameters added. Giving up slices 18 times
- ; a second is a bit much.
- ;
- ; 11 Nov. 1995 -- 4th release -- Began adding tuning parameters. Fixed a bug in the int 1C
- ; ISR. The IRET in the old int 2F handler was popping AX
- ; instead of the flags. Rearranged the push ax and the pushf
- ; to fix it.
- ;
- ; 23 Nov. 1995 -- 5th release -- Added elapsed tick counter, and logic to increment it on every
- ; timer tick, to the int 1C isr. In order to make this work, I
- ; had to use the CS segment override on the inc instruction. I
- ; intend to use this to trigger the call to int 2F, function 1680h
- ; after so many ticks as opposed to every one.
- ; -- Added whenmask to hold a value for controlling when to release a
- ; CPU cycle. Essentially I AND elapsed with whenmask, and if the
- ; is not zero then it's time to release a CPU cycle. Currently
- ; whenmask is set at 4, so int 2F, function 1680h is getting
- ; called every 4 ticks instead of every tick.
- ;
- ; 24 Nov. 1995 -- 6th release -- Corrected bug with the trigger logic. Logical AND is not the
- ; proper way to do this, because it does not cause the event
- ; to happen every whenmask ticks. Changed it to use straight
- ; comparison, and elapsed to reflect ticks since last event.
- ; It is much smoother now.
- ; -- Added code in the installation portion of the program to find
- ; the trigger interval on the command line passed as /XX where
- ; for the present both digits must be passed. XX can range from
- ; 0 to 99. If nothing is passed, the default is every 4 ticks.
- ;
- ; 24 Nov. 1995 -- 7th release -- Changed the ownership message to reflect the Bionic Fish
- ; Software Foundry. This is preparatory to releasing as freeware.
- ; Freeware release will occur 24 Nov. 1995 via upload to EXEC-PC.
- ;
- ; 20 Feb. 1996 -- 8th release -- Began working on V1R8. Will not allow Disk I/O or Mouse operations
- ; to be interrupted. This will be accomplished by creating a
- ; semaphore variable, and using it control whether the interruption
- ; occurs when it is supposed to. Instead, it will reset the counter
- ; to zero, and IRET. The mouse will be done first, and I am going
- ; to assume the mouse is MS compatible, and has an Int 33h API.
- ; -- Code for the mouse exclusion is in place. Sema is the semaphore
- ; variable. 0 = activation allowed, >0 = activation NOT allowed.
- ; Because I will also use this semaphore for the Disk I/O, I must
- ; accept that the semaphore may be greater than 1, because a disk
- ; event may be interrupted by a mouse event and vice versa.
- ; -- Code for trapping int 33h, mouse api, is in place. A simple wrapper,
- ; it should cause extremely minimal performance degradation.
- ; -- Because of the code required for hooking the mouse interrupt, the
- ; conditional jmp at the end of the install_chek had to be modified.
- ; The conditional jump now checks if installation has not occured, and
- ; bypasses the unconditional jmp if it has NOT.
- ; -- Code for Disk I/O trapping, BIOS int 13h, is in place. Same concept
- ; as the mouse trap.
- ; -- With both of these changes in place, performance in a full screen DOS
- ; session under OS/2 Warp with the interval set at 6 ticks, AutoSketch
- ; runs noticeably better than it did, but not better enough. More work
- ; must be done to improve overall system performance. However, I am
- ; putting it into production on my system today.
- ;
- ; 08 Mar. 1996 -- 9th release -- Added code to retrieve the address of the In-DOS flag during the install
- ; phase. The address is stored in the indos_flg variable. I have not
- ; decided how to use the In-DOS flag, however.
- ; -- Added code to retrieve the address of the DOS Critical Error flag. The
- ; address is stored in the crter_flg variable. As with the In-DOS flag,
- ; I haven't decided how to use it.
- ; -- Changed the jne conditional jump in the elapsed to whenmask comparison
- ; to a jb jump. This will guarantee that the release will happen and
- ; get resynchronized if elapsed should happen to become greater than
- ; whenmask.
- ; -- Added code to the Int 1C isr to check the In-DOS flag and prevent
- ; activation if set.
- ; -- Added code to the Int 1C isr to check the Critical Error flag and
- ; prevent activation if set.
- ; -- Removed Hard Disk BIOS & Mouse Semaphores. The Critical Error and
- ; In-DOS flag checks do much better.
- ; -- Added code to hook the DOS Idle Interrupt, Int 28h. Since the In-DOS
- ; flag is set during an Int 28h call, it is necessary to hook this in
- ; order for cycles to be released during input wait loops. Unlike the
- ; Int 1Ch isr, the Int 28h service routine releases cycles every time
- ; it is invoked.
- ; -- Works great!! The only hitch is a slower ramp up to maximum file xfer
- ; speed in Telix for Windows. However, the fact that Windows runs under
- ; OS/2 Warp with give-up being loaded in the OS/2 autoexec.bat speaks
- ; major things about this release. It goes into production in my OS/2
- ; autoexec.bat today. This means every WIN-OS/2 session will have give-up
- ; running in the background.
- ;
- ; 09 Mar. 1996 --10th release -- The final modification before releasing this as a new version is a change
- ; to the loader. Instead of executing and then going TSR, I think it
- ; allocate a block of DOS memory as high in MCB chain as possible, copy
- ; only the ISRs and their data into it, changing the allocated MCB's
- ; owner to 0x08h, MS-DOS, linking the ISRs into the IVT chains, and then
- ; exiting normally. By allocating the memory from the top, a hole will
- ; not be left when the loader portion terminates. In order for this to work,
- ; it is necessary to reallocate the MCB used by give-up itself.
- ; -- Added code to reallocate the Give-up MCB to only the actual amount used.
- ; -- Added code to allocate a block of memory and then change its owner to DOS.
- ; This block of memory will not get released when the program terminates.
- ; -- Added code to calculate the new ISR offsets. When the code is moved into
- ; the new segment, the offsets will be true offsets from the beginning of
- ; the segment, as opposed to the beginning of a .COM program where the PSP
- ; must be accounted for.
- ; -- Added code to copy the ISR code and data to its new location in memory.
- ; -- Removed TSR memory calculation and TSR exit code. Also changed the exit
- ; label from not_tsr_exit to plain exit.
- ; -- Because all of the original offsets and addresses are calculated with an
- ; ORG of 256 because this starts as a .COM program, I had to adjust all of
- ; the offsets in variable and address references in the ISR routines.
- ; These are the -256 additions throughout this sections of the code.
- ; -- Works!! memory footprint is a mere 160 bytes!! Going into production use.
- ;
- ; 23 Mar. 1996 --11th release -- Officially changing the version from v1r10 to v2r1, and corrected the startup
- ; message to reflect this. Will release to Exec-pc on Sunday, 24 Mar. 1996.
-
- _CODE SEGMENT
- ASSUME CS:_CODE, DS:_CODE, ES:_CODE
- ORG 100h
-
- start:
- jmp install ; Jump to the installation code
-
- oldint1c dd 00000000h ; Old int 1Ch, timer, ivt entry
- oldint28 dd 00000000h ; Old int 28h, DOS Idle, ivt entry
- oldint2f dd 00000000h ; Old int 2Fh, multiplex, ivt entry
-
- indos_flg dd 00000000h ; Address of In-DOS flag
- crter_flg dd 00000000h ; Address of Critical Error Flag
-
- elapsed dw 0000h ; Ticks elapsed since program load
- whenmask dw 0004h ; When to activate
-
- int28_isr: ; Interrupt 28h, ISR
- pushf ; Push flags onto stack
- call cs:oldint28-256 ; Transfer control to old interrupt handler
- push ax ; Preserve AX
- mov ax,1680h ; Int 2F, function 1680h, Release current time slice
- pushf ; Push flags onto stack
- call cs:oldint2f-256 ; Call multiplex interrupt
- pop ax ; Restore AX
- iret ; Interrupt return
-
- int2f_isr: ; Interrupt 2Fh ISR
- cmp ax,0BADDh ; 0xBADD is my multiplex ID
- je int2f_isr_srvc ; If AX=0xBADDh then service the request
- jmp cs:oldint2f-256 ; Transfer control to old int 2Fh ISR otherwise
- int2f_isr_srvc: ; Custom int 2Fh code is here
- mov ax,0FADEh ; AX=0xFADEh, then GIVE-UP is installed
- iret ; Interrupt return
-
- int1c_isr: ; Interrupt 1Ch ISR
- pushf ; Push flags onto stack
- call cs:oldint1c-256 ; Transfer control to the old interrupt handler
- push bx ; Preserve BX
- mov bx,word ptr cs:[elapsed-256] ; Copy to temporary storage
- cmp bx,word ptr cs:[whenmask-256] ; Is it time to trigger
- pop bx ; Restore BX
- jb int1c_isr_inc ; If less than then increment elapsed and return
- push ax ; Preserve AX
- push bx ; Preserve BX
- push es ; Preserve ES
- mov ax,0001h ; Set AX to 1
- mov bx,word ptr cs:[indos_flg+2-256] ; Point ES to In-DOS flag
- mov es,bx
- mov bx,word ptr cs:[indos_flg-256] ; Point BX to In-DOS flag
- cmp al,byte ptr es:[bx] ; See if In-DOS flag is set
- pop es ; Restore ES
- pop bx ; Restore BX
- pop ax ; Restore AX
- jae int1c_isr_reset ; If In-DOS is set reset elapsed and return
- push ax ; Preserve AX
- push bx ; Preserve BX
- push es ; Preserve ES
- mov ax,0001h ; Set AX to 1
- mov bx,word ptr cs:[crter_flg+2-256] ; Point ES to Critical Error flag
- mov es,bx
- mov bx,word ptr cs:[crter_flg-256] ; Point BX to Critical Error flag
- cmp al,byte ptr es:[bx] ; See if Critical Error flag is set
- pop es ; Restore ES
- pop bx ; Restore BX
- pop ax ; Restore AX
- jae int1c_isr_reset ; If Critical Error is set reset elapsed and return
- push ax ; Preserve AX
- mov ax,1680h ; Int 2F, function 1680h, Release current time slice
- pushf ; Push flags onto stack
- call cs:oldint2f-256 ; Call multiplex interrupt
- pop ax ; Restore AX
- int1c_isr_reset:
- mov word ptr cs:[elapsed-256],0000h ; Reset elapsed to zero
- jmp int1c_isr_end ; Jump to IRET
- int1c_isr_inc:
- inc word ptr cs:[elapsed-256] ; Increment elapsed tick counter
- int1c_isr_end:
- iret ; Interrupt return from procedure
-
- endmark: ; Used for TSR paragraph calc
-
- install:
- mov bx,cs ; Initialize DS & ES to equal CS
- mov ds,bx
- mov es,bx
-
- mov ax,offset giveup_end ; Store size of full program into AX
- mov cl,04h ; Divide AX by 4 to get paragraphs
- shr ax,cl ; Paragraphs now in AX
- inc ax ; Add one for good measure
- mov bx,ax ; Paragraph size goes in BX
- mov ax,4A00h ; DOS func 4A, Resize memory block
- int 21h ; Call DOS
-
- mov ah,49h ; DOS function 49h, release memory block
- mov bx,2Ch ; Offset in PSP of program environment segment address
- mov cx,word ptr es:[bx] ; Retrieve that segment address into CX
- mov es,cx ; And load into ES
- int 21h ; Call DOS
- mov bx,cs ; Reset ES
- mov es,bx
-
- mov ah,09h ; DOS Print message function
- mov dx,offset msg0 ; Print ownership message
- int 21h ; Call DOS
-
- install_chek: ; Check if already installed
- mov ax,0BADDh ; GIVE-UP multiplex ID is BADDh
- int 2Fh ; Call multiplex interrupt
- cmp ax,0FADEh ; AX=FADEh GIVE-UP is installed
- jne cmd_line ; If not installed the continue
- jmp already_installed ; Do nothing and exit
-
- cmd_line: ; Find trigger interval on command line
- cld ; Clear direction flag (Count upward)
- mov di,0080h ; Offset of command tail in PSP
- mov cx,007Fh ; Length of command tail in PSP
- mov al,0Dh ; Character to search for (CR first to prevent screwups w/OS2)
- repne scasb ; Scan for CR
- mov cx,di ; Move offset of CR into CX
- sub cx,0080h ; Subtract 80h, this is new max scan length
- mov di,0080h ; Offset of command tail in PSP
- mov al,'/' ; Character to search for
- repne scasb ; Scan for /
- cmp cl,00h ; If CL = 0 then / was not found
- je loader ; Load with default of every 4 ticks
- mov word ptr cs:[whenmask],0000h ; Zero the trigger interval
- mov al,byte ptr es:[di] ; Move the byte into AL
- sub al,30h ; Convert from ASCII into a number
- mov bl,10 ; Store 10 into BL
- xor ah,ah ; Zero AH
- mul bl ; Multiply by 10
- add word ptr cs:[whenmask],ax ; Add it to the trigger interval
- inc di ; Increment DI to next character
- mov al,byte ptr es:[di] ; Move the byte into AL
- sub al,30h ; Convert from ASCII into a number
- xor ah,ah ; Zero AH
- add word ptr cs:[whenmask],ax ; Add it to the trigger interval
-
- loader: ; Install the ISRs and their data
- mov ax,5800h ; DOS function 58, sub func 00, Get allocation strategy
- int 21h ; Call DOS
- mov word ptr cs:[strat],ax ; Store the current allocation strategy
-
- mov ax,5801h ; DOS function 58, sub func 01, Set allocation strategy
- mov bx,0002h ; To a last fit strategy
- int 21h ; Call DOS
-
- mov bx,offset start ; Get the offset of the start label
- mov ax,offset endmark ; Get offset of the endmark label
- sub ax,bx ; Find number of bytes between start and endmark
- mov cl,04h ; Divide AX by 16 to get paragraphs
- shr ax,cl ; Paragraphs now in AX
- inc ax ; Just in case
-
- mov bx,ax ; Store number of paragraphs into BX
- mov ax,4800h ; DOS func. 48h, allocate memory
- int 21h ; Call DOS
- mov word ptr cs:[iseg],ax ; Store newly allocated segment address
-
- mov ax,5801h ; DOS function 58, sub func 01, Set allocation strategy
- mov bx,word ptr cs:[strat] ; Restore the current strategy
- int 21h ; Call DOS
-
- push es ; Preserve ES
- mov ax,word ptr cs:[iseg] ; Load the ISR segment
- dec ax ; Decrementing it points it to the correct MCB
- mov es,ax ; Point ES to it
- mov bx,0001h ; Offset in MCB of owner PID
- mov word ptr es:[bx],0008h ; DOS' PID is always 8
- pop es ; Restore ES
-
- mov ax,offset int1c_isr ; Calculate the Int 1Ch isr offset
- sub ax,256 ; By subtracting the PSP, the new offset is left
- mov word ptr cs:[off1c],ax ; Store it out
-
- mov ax,offset int28_isr ; Calculate the Int 28h isr offset
- sub ax,256 ; By subtracting the PSP, the new offset is left
- mov word ptr cs:[off28],ax ; Store it out
-
- mov ax,offset int2f_isr ; Calculate the Int 2fh isr offset
- sub ax,256 ; By subtracting the PSP, the new offset is left
- mov word ptr cs:[off2f],ax ; Store it out
-
- mov ax,3400h ; Int 21h, func 3400h, Get In-DOS flag address
- int 21h ; Call DOS
- mov word ptr [indos_flg],bx ; Offset of In-DOS flag
- mov word ptr [indos_flg+2],es ; Segment of In-DOS flag
-
- push ds ; Preserve DS
- push si ; Preserve SI
- mov ax,5D06h ; Int 21h, func 5D06h, Get DOS Swappable Data Area
- int 21h ; Call DOS
- mov word ptr [crter_flg],si ; Offset of Critical Error Flag
- mov word ptr [crter_flg+2],ds ; Segment of Critical Error Flag
- pop si ; Restore SI
- pop ds ; Restore DS
-
- mov ax,351Ch ; Save the current INT 1Ch handler address
- int 21h ; Call DOS
- mov word ptr [oldint1c],bx ; Offset of INT 1Ch ISR
- mov word ptr [oldint1c+2],es ; Segment of INT 1Ch ISR
-
- mov ax,3528h ; Save the current INT 28h handler address
- int 21h ; Call DOS
- mov word ptr [oldint28],bx ; Offset of INT 28h ISR
- mov word ptr [oldint28+2],es ; Segment of INT 1Ch ISR
-
- mov ax,352fh ; Save the current INT 2fh handler address
- int 21h ; Call DOS
- mov word ptr [oldint2f],bx ; Offset of INT 2fh ISR
- mov word ptr [oldint2f+2],es ; Segment of INT 2fh ISR
-
- push es ; Preserve ES
- push ds ; Preserve DS
- push di ; Preserve DI
- push si ; Preserve SI
- pushf ; Preserve the flags
- mov bx,word ptr cs:[iseg] ; Point ES to the new ISR segment
- mov es,bx
- mov si,offset start ; DS:SI points to source
- mov di,0000h ; ES:DI points to destination
- mov bx,offset start ; BX holds start
- mov ax,offset endmark ; AX holds endmark
- sub ax,bx ; AX holds number of bytes to copy
- mov cx,ax ; Now CX holds it
- cld ; Copy goes from lo to hi
- rep movsb ; Copy all of the ISR code and data to its new home
- popf ; Restore the flags
- pop si ; Restore SI
- pop di ; Restore DI
- pop ds ; Restore DS
- pop es ; Restore ES
-
- push ds ; Preserve DS
- mov bx,word ptr cs:[iseg] ; Point DS to new ISR segment
- mov ds,bx
-
- mov ax,251Ch ; Insert my own Int 1Ch handler in ISR chain
- mov dx,word ptr cs:[off1c] ; DS:DX points to ISR
- int 21h ; Call DOS
-
- mov ax,2528h ; Insert my own Int 1Ch handler in ISR chain
- mov dx,word ptr cs:[off28] ; DS:DX points to ISR
- int 21h ; Call DOS
-
- mov ax,252fh ; Insert my own Int 2Fh handler in ISR chain
- mov dx,word ptr cs:[off2f] ; DS:DX points to ISR
- int 21h ; Call DOS
- pop ds ; Restore DS
- mov ax,4C00h ; Terminate with errorlevel=0
- jmp exit ; And exit
-
- already_installed:
- mov ah,09h ; Print already installed message
- mov dx,offset msg4
- int 21h ; Call DOS
- mov ax,4CFFh ; If no revectoring then errorlevel=255
-
- exit: ; Terminate normally
- int 21h ; Call DOS
-
-
- ; Data at end of code so it isn't kept when program goes TSR
- strat dw 0000h ; DOS allocation strategy
- iseg dw 0000h ; Segment allocated for ISRs and data
-
- off1c dw 0000h ; Offset of int 1Ch isr
- off28 dw 0000h ; Offset of int 28h isr
- off2f dw 0000h ; Offset of int 2Fh isr
-
- msg0 db 13,10,'GIVE-UP TSR for OS/2, WinNT, Win95 & WFW',13,10
- msg1 db 'By: Paul Trout, Bionic Fish Software Foundry',13,10
- msg2 db '23 Mar. 1996 -- V2R1',13,10,13,10,'$'
- msg4 db 'GIVE-UP already installed, Not going TSR',13,10,'$'
-
- giveup_end: ; True end of program marker
- _CODE ENDS
- END start
-
-